/**
 * 着色器的用途
 *  在3D场景中，仅仅用线条和颜色把图元画出来是远远不够的。
 *  必须考虑，比如，光纤照上去之后，或者观察者的视角发生变化，对场景会有些什么影响
 *  着色器可以高度灵活地完成这些工作，提供各种渲染效果。
 */
/**
 * varying变量：作用是从顶点着色器向片元着色器传输数据
 */



 import { baseError } from '../../debug'

 /**
  * 在初始化着色器之前，顶点着色器和片元着色器都是空白的，需要将字符串形式的着色器代码从
  *  JS传给WebGL系统，并建立着色器。这是initShaders()做的事情
  * @param gl GL context
  * @param vshader a vertex shader program (string)
  * @param fshader a fragment shader program (string)
  * @return true, if the program object was created and successfully made current 
  */
 // vshader(顶点着色器)：用来描述顶点特性(如位置、尺寸等)的程序。
 // fshader(片元着色器)：进行逐片元处理过程如光照的程序(片元可理解为像素)
 // 在顶点着色器和片元着色器之间，有两个步骤:P145对其的分析
 // 1. 图形装配过程：将孤立的顶点坐标装配成几何图形。几何图形的类别由gl.drawArrays()
 export function initShaders(gl, vshader, fshader) {
   let program = createProgram(gl, vshader, fshader);
   if (!program) {
     baseError('Failed to create program');
     return false;
   }
 
   gl.useProgram(program);
   gl.program = program;
 
   return true;
 }
 /**
  * Create the linked program object
  * @param gl GL context
  * @param vshader a vertex shader program (string)
  * @param fshader a fragment shader program (string)
  * @return created program object, or null if the creation has failed
  */
 function createProgram(gl, vshader, fshader) {
   // Create shader object
   var vertexShader = loadShader(gl, gl.VERTEX_SHADER, vshader);
   var fragmentShader = loadShader(gl, gl.FRAGMENT_SHADER, fshader);
   if (!vertexShader || !fragmentShader) {
     return null;
   }
 
   // Create a program object
   var program = gl.createProgram();
   if (!program) {
     return null;
   }
 
   // Attach the shader objects
   gl.attachShader(program, vertexShader);
   gl.attachShader(program, fragmentShader);
 
   // Link the program object
   gl.linkProgram(program);
 
   // Check the result of linking
   var linked = gl.getProgramParameter(program, gl.LINK_STATUS);
   if (!linked) {
     var error = gl.getProgramInfoLog(program);
 
     console.log('Failed to link program: ' + error);
     gl.deleteProgram(program);
     gl.deleteShader(fragmentShader);
     gl.deleteShader(vertexShader);
     return null;
   }
   return program;
 }
 
 /**
  * Create a shader object
  * @param gl GL context
  * @param type the type of the shader object to be created
  * @param source shader program (string)
  * @return created shader object, or null if the creation has failed.
  */
 function loadShader(gl, type, source) {
   // Create shader object
   var shader = gl.createShader(type);
   if (shader == null) {
     console.log('unable to create shader');
     return null;
   }
 
   // Set the shader program
   gl.shaderSource(shader, source);
 
   // Compile the shader
   gl.compileShader(shader);
 
   // Check the result of compilation
   var compiled = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
   if (!compiled) {
     var error = gl.getShaderInfoLog(shader);
     baseError('Failed to compile shader: ' + error);
     gl.deleteShader(shader);
     return null;
   }
 
   return shader;
 }